package com.wanlian.util;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.log4j.Logger;
import org.bouncycastle.util.Times;
import org.springframework.util.StringUtils;

public class DateUtil {

    protected static Logger logger = Logger.getLogger(DateUtil.class);

    private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat sdfNOHour = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
    private static final SimpleDateFormat sdfNOHourPar = new SimpleDateFormat("yyyy-MM-dd");

    public static Date addDay(Date date, int days) {
        // 空值判断
        if (date == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, days);
        return c.getTime();
    }

    public static Date addMonth(Date date, int months) {
        // 空值判断
        if (date == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, months);
        return c.getTime();
    }

    public static Date clearHour(Date date) {
        // 空值判断
        if (date == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    public static Date clearMinuter(Date date) {
        // 空值判断
        if (date == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    public static Integer getWeekOfYear(Date date) {
        // 空值判断
        if (date == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.WEEK_OF_YEAR);
    }

    public static Integer getMonthOfYear(Date date) {
        // 空值判断
        if (date == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.MONTH) + 1;
    }

    public static Integer getYear(Date date) {
        // 空值判断
        if (date == null) {
            return null;
        }

        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return c.get(Calendar.YEAR);
    }

    public static boolean afterDate(Date first, Date second) {
        // 空值判断
        if (first == null || second == null) {
            return false;
        }

        return first.getTime() - second.getTime() < 0 ? true : false;
    }

    public static boolean afterToday(Date first) {
        if (first == null) {
            return false;
        }

        return first.getTime() - System.currentTimeMillis() < 0 ? true : false;
    }

    /**
     * 判断日期
     *
     * @param first
     * @return
     */
    public static boolean beforeToday(Timestamp first) {
        if (first == null) {
            return false;
        }
        return first.getTime() - currentDateTimestamp().getTime() < 0 ? true : false;
    }

    /**
     * 判断日期
     *
     * @param first
     * @return
     */
    public static boolean beforeNow(Timestamp first) {
        if (first == null) {
            return false;
        }
        return first.getTime() - currentTimestamp().getTime() < 0 ? true : false;
    }

    //返回值格式：2017-01-05 00:00:00
    public static Timestamp currentDateTimestamp() {
        Date date = new java.util.Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd 00:00:00");
        String st = formatter.format(date);
        Timestamp time = Timestamp.valueOf(st);
        return time;
    }

    // 返回值格式：2017-01-05 17:56:45.801
    public static Timestamp currentTimestamp() {
        return new java.sql.Timestamp(new java.util.Date().getTime());
    }

    public static String currentAuDatetime() {
        // 设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        return df.format(new Date());
    }

    // 返回值格式：2017-01-05 18:00:34
    public static String currentDatetime() {
        // 设置日期格式
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        return df.format(new Date());
    }

    // 跟据自己传入的格式将时间转换成自己传入的那种格式
    // 举例：传入的格式为"yyyyMMddHHmmssSSS" 返回日期格式为：20170119120835001
    public static String currentDatetime(String timeFormat) {
        // 空值判断
        if (StringUtils.isEmpty(timeFormat)) {
            return "";
        }

        SimpleDateFormat df = new SimpleDateFormat(timeFormat);
        return df.format(new Date());
    }

    // 传入的的文件原文件名加上后面的时间构建成一个新的文件名，传入参数不包含后缀名
    // 举例：传入的文件名为“我的照片”，那么构建后的新文件名是“我的照片_20170119_122409_937”
    public static String fileNameWithCurrentTimestamp(String filePrefix) {
        String dateTimeStr = DateUtil.currentDatetime("yyyyMMdd_HHmmss_SSS");
        String newFileName = filePrefix + "_" + dateTimeStr;

        return newFileName;
    }

    // 传入的的文件原文件名加上后面的时间构建成一个新的文件名，传入参数后缀名
    // 举例：传入的文件名为“我的照片.jpg”，那么构建后的新文件名是“我的照片_20170119_122409_937.jpg”
    public static String fileNameWithTimestampAndSuffix(String fileFullName) {

        int pointIndex = fileFullName.indexOf("."); // 获得文件名中点的下标
        String filePrefix = fileFullName.substring(0, pointIndex); // 截取文件中“.”之前的字符串。
        String fileSuffix = fileFullName.substring(pointIndex); // 根据点的下标来截取点后面的后缀名。

        /*
         * 通过原始名与当前时间构建出来一个新的文件名
         *
         */
        String fileNameWithTime = DateUtil.fileNameWithCurrentTimestamp(filePrefix);
        // String saveFileName = fileNameWithTime + "." + fileSuffix;
        String saveFullFileName = fileNameWithTime + fileSuffix;

        return saveFullFileName;
    }

    // 传入的的文件原文件名加上后面的时间构建成一个新的文件名
    public static String fileNameWithCurrentDate(String filePrefix) {
        String dateTimeStr = DateUtil.currentDatetime("yyyyMMdd");
        String newFileName = filePrefix + "_" + dateTimeStr;

        return newFileName;
    }

    // 返回值格式：Thu Jan 05 18:00:34 CST 2017
    public static Date currentDate() {
        return new Date();
    }

    // 判断日期是否合法
    public static boolean isValidDate(String srcStrDate) {
        // 空值判断
        if (StringUtils.isEmpty(srcStrDate)) {
            return false;
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        dateFormat.setLenient(false);
        Date srcDate = null;
        Date rangeStartDate = null;
        Date rangeEndDate = null;

        try {
            srcDate = dateFormat.parse(srcStrDate);
            rangeStartDate = dateFormat.parse("1900-01-01");
            rangeEndDate = dateFormat.parse("2100-12-31");
        } catch (ParseException e) {
            logger.error("公共组件：按指定格式解析日期字符串时产生异常", e);
            return false;
        }

        // 日期范围判断：判断日期是否在"1900-01-01"与"2100-12-31"之间
        if (DateUtil.afterDate(srcDate, rangeStartDate) || DateUtil.afterDate(rangeEndDate, srcDate)) {
            return false;
        }

        return true;
    }

    // 根据格式匹配返回日期
    public static Date stringToDate(String pattern, String srcDate) {
        if (StringUtils.isEmpty(pattern) || StringUtils.isEmpty(srcDate)) {
            return null;
        }

        Date dstDate = null;
        SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
        try {
            dstDate = dateFormat.parse(srcDate);
        } catch (ParseException e) {
            logger.error("公共组件：按指定格式解析日期字符串时产生异常", e);
            return null;
        }
        return dstDate;
    }

    public static String dateToString(String pattern, Date srcDate) {
        return srcDate == null ? "" : new SimpleDateFormat(pattern).format(srcDate);
    }

    /**
     * 返回间隔天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int getDayInterval(Date date1, Date date2) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        String sDate1 = df.format(date1);
        String sDate2 = df.format(date2);
        Date date3 = new Date();
        Date date4 = new Date();
        try {
            date3 = df.parse(sDate1);
            date4 = df.parse(sDate2);
        } catch (ParseException e) {
            logger.error("公共组件：获取两天之间的间隔时产生异常", e);
            return -1;
        }

        int days = (int) ((date4.getTime() - date3.getTime()) / (24 * 60 * 60 * 1000));
        return days;
    }

    /**
     * 返回间隔天数
     *
     * @param startTimestamp
     * @param endTimestamp
     * @return
     */
    public static int getDateInterval(Timestamp startTimestamp, Timestamp endTimestamp) {
        long interval = endTimestamp.getTime() - startTimestamp.getTime();
        return (int) (interval / (1000 * 60 * 60 * 24));
    }

    /**
     * 返回间隔多少秒
     *
     * @param startTimestamp
     * @param endTimestamp
     * @return
     */
    public static int getSecondInterval(Timestamp startTimestamp, Timestamp endTimestamp) {
        long interval = endTimestamp.getTime() - startTimestamp.getTime();
        return (int) interval / 1000;
    }

    /**
     * 返回间隔多少秒
     *
     * @param startTimeMillis
     * @param endTimeMillis
     * @return
     */
    public static int getSecondInterval(long startTimeMillis, long endTimeMillis) {
        return (int) (endTimeMillis - startTimeMillis) / 1000;
    }

    public static String formatISODate(Date date) {
        return date == null ? "" : DateFormatUtils.ISO_DATE_FORMAT.format(date);
    }

    public static String formatISOTime(Date date) {
        return date == null ? "" : DateFormatUtils.ISO_TIME_NO_T_FORMAT.format(date);
    }

    public static String formatISODateTime(Date date) {
        return date == null ? "" : DateFormatUtils.ISO_DATETIME_FORMAT.format(date);
    }

    /**
     * 之前多少分
     *
     * @param minutes
     * @return
     */
    public static boolean beforeMinute(int minutes) {
        Date dateNow = DateUtil.currentDate();
        Date dateEnd = DateUtil.addDay(dateNow, -1);
        return true;
    }

    /**
     * @param seconds
     * @return
     */
    public static boolean beforeSeconds(int seconds) {
        return true;
    }

    /**
     * @param hours
     * @return
     */
    public static boolean beforeHours(int hours) {
        return true;
    }


    public static Timestamp addTimeToDate(Timestamp timestamp) {
        long time = timestamp.getTime() + 24 * 60 * 60 * 1000 - 1;
        Timestamp result = new Timestamp(time);
        return result;
    }


    public static boolean belongCalendar(String time, String from, String to) {
        Date fromDate = stringToDate("yyyy-MM-dd", from);
        Date toDate = stringToDate("yyyy-MM-dd", to);
        Date timedate = stringToDate("yyyy-MM-dd", time);
        Calendar date = Calendar.getInstance();
        date.setTime(timedate);

        Calendar after = Calendar.getInstance();
        after.setTime(fromDate);

        Calendar before = Calendar.getInstance();
        before.setTime(toDate);

        if (date.after(after) && date.before(before)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean belongCalendar(Date time, Date from, Date to) {
        Calendar date = Calendar.getInstance();
        date.setTime(time);

        Calendar after = Calendar.getInstance();
        after.setTime(from);

        Calendar before = Calendar.getInstance();
        before.setTime(to);

        if (date.after(after) && date.before(before)) {
            return true;
        } else {
            return false;
        }
    }


    public static String getTimeByTimestamp(Timestamp timestamp) {
        String tsStr = "";
        DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            // 方法一
            tsStr = sdf.format(timestamp);
            // System.out.println(tsStr);
            // 方法二
            // tsStr = ts.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tsStr;
    }

    public static String getDataByTimestamp(Timestamp timestamp) {
        String tsStr = "";
        DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        try {
            // 方法一
            tsStr = sdf.format(timestamp);
            // System.out.println(tsStr);
            // 方法二
            // tsStr = ts.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tsStr;
    }

    public static String getStrDataByTimestamp(Timestamp timestamp) {
        // Timestamp ts = new Timestamp(System.currentTimeMillis());
        String tsStr = "";
        DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        try {
            // 方法一
            tsStr = sdf.format(timestamp);
            // System.out.println(tsStr);
            // 方法二
            // tsStr = ts.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return tsStr;
    }

    public static String formatDate(Date date) throws ParseException {
        return sdf.format(date);
    }

    public static String formatDateNoHour(Date date) throws ParseException {
        return sdfNOHour.format(date);
    }

    public static String formatDateNoHourPartern(Date date) throws ParseException {
        return sdfNOHourPar.format(date);
    }

    public static Date parse(String strDate) throws ParseException {
        return sdf.parse(strDate);
    }

    public static boolean isYesterday(long timestamp) {
        Calendar c = Calendar.getInstance();
        clearCalendar(c, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND);
        c.add(Calendar.DAY_OF_MONTH, -1);
        long firstOfDay = c.getTimeInMillis(); // 昨天最早时间
        c.setTimeInMillis(timestamp);
        clearCalendar(c, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND, Calendar.MILLISECOND); // 指定时间戳当天最早时间
        return firstOfDay == c.getTimeInMillis();
    }

    private static void clearCalendar(Calendar c, int... fields) {
        for (int f : fields) {
            c.set(f, 0);
        }
    }

    /**
     * 获取昨日时间戳
     *
     * @return
     */
    public static Timestamp getYestoryDayTimeStamp() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.addDay(DateUtil.currentDate(), -1));
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        Timestamp timestamp = new Timestamp(calendar.getTimeInMillis());
        return timestamp;
    }

    /**
     * 是否属于同一天
     *
     * @param t1
     * @param t2
     * @return
     */
    public static boolean isSameDay(Timestamp t1, Timestamp t2) {
        if (t1 == null | t2 == null) {
            return false;
        }
        String tday1 = getDataByTimestamp(t1);
        String tday2 = getDataByTimestamp(t2);
        if (tday1.equals(tday2)) {
            return true;
        } else {
            return false;
        }
    }

    public static void main(String args[]) throws ParseException {
        System.out.println(DateUtil.currentTimestamp().getTime());
        Timestamp timestamp = getYestoryDayTimeStamp();
        Timestamp timestamp2 = new Timestamp(DateUtil.currentTimestamp().getTime());
        System.out.println(DateUtil.isSameDay(timestamp, timestamp2));
    }

}
